{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# Torchvision（上）：数据读取，训练开始的第一步",
   "id": "7f8c86e21ff22d95"
  },
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "import torch\n",
    "from tensorboard.notebook import display\n",
    "from torch.utils.data import Dataset\n",
    "from torchvision.transforms import InterpolationMode"
   ],
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "class MyDataset(Dataset):\n",
    "  # 构造函数\n",
    "  def __init__(self, data_tensor, target_tensor):\n",
    "    self.data_tensor = data_tensor\n",
    "    self.target_tensor = target_tensor\n",
    "  # 返回数据集⼤⼩\n",
    "  def __len__(self):\n",
    "    return self.data_tensor.size(0)\n",
    "  # 返回索引的数据与标签\n",
    "  def __getitem__(self, index):\n",
    "    return self.data_tensor[index], self.target_tensor[index]"
   ],
   "id": "10cd7951f85b62d",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "# ⽣成数据\n",
    "data_tensor = torch.randn(10, 3)\n",
    "target_tensor = torch.randint(2, (10,)) # 标签是0或1\n",
    "\n",
    "# 将数据封装成Dataset\n",
    "my_dataset = MyDataset(data_tensor, target_tensor)\n",
    "\n",
    "# 查看数据集⼤⼩\n",
    "print('Dataset size:', len(my_dataset))\n",
    "\n",
    "# 使⽤索引调⽤数据\n",
    "print('tensor_data[0]: ', my_dataset[1])"
   ],
   "id": "a69814774d873cbe",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": "from torch.utils.data import DataLoader",
   "id": "5b39bb7a1ab74246",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "tensor_dataloader = DataLoader(dataset=my_dataset, # 传⼊的数据集, 必须参数\n",
    "                               batch_size=2, # 输出的batch⼤⼩\n",
    "                               shuffle=True, # 数据是否打乱\n",
    "                               num_workers=0) # 进程数, 0表示只有主进程\n",
    "\n",
    "# 以循环形式输出\n",
    "for data, target in tensor_dataloader:\n",
    "    print(data, target)\n",
    "\n",
    "# 输出⼀个batch\n",
    "print('One batch tensor data: ', iter(tensor_dataloader)._next_data())"
   ],
   "id": "507ed4c2667fd59b",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "Torchvision 库中的torchvision.datasets包中提供了丰富的图像数据集的接⼝。常⽤\n",
    "的图像数据集，例如 MNIST、COCO 等，这个模块都为我们做了相应的封装。\n",
    "下表中列出了torchvision.datasets包所有⽀持的数据集。各个数据集的说明与接\n",
    "⼝，详⻅链接https://pytorch.org/vision/stable/datasets.html。"
   ],
   "id": "863cbf63dda64e78"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "import torchvision\n",
    "\n",
    "mnist_dataset = torchvision.datasets.MNIST(root='./data', #数据集位置\n",
    "                                           train=True, #是否加载训练集\n",
    "                                           transform=None, #是否对图像进行预处理操作\n",
    "                                           target_transform=None, # 用于对图像标签进行预处理工作\n",
    "                                           download=True) #是否下载数据集\n",
    "mnist_dataset_list = list(mnist_dataset)\n",
    "print(mnist_dataset_list[0])"
   ],
   "id": "df4047dc2a08eede",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "display(mnist_dataset_list[0][0])\n",
    "print(\"Image label is: \", mnist_dataset_list[0][1])"
   ],
   "id": "c2919ceffbee095c",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "练习: 在 PyTorch 中，我们要定义⼀个数据集，应该继承哪⼀个类呢？\n",
    "\n",
    "答: torch.utils.data.Dataset (这是 PyTorch 数据加载系统的基础类，用于创建你自己的数据集对象，以便与 DataLoader 搭配使用)"
   ],
   "id": "faff51ea4326f559"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# Torchvision（中）：数据增强，让数据更加多样性",
   "id": "b020d8dfd6ae31c0"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 图像处理⼯具之 torchvision.transforms\n",
    "Torchvision 库中的torchvision.transforms包中提供了常⽤的图像操作，包括对Tensor 及 PIL Image 对象的操作，例如随机切割、旋转、数据类型转换等等。\n",
    "按照torchvision.transforms 的功能，⼤致分为以下⼏类：数据类型转换、对PIL.Image 和 Tensor 进⾏变化和变换的组合。下⾯我们依次来学习这些类别中的操作。"
   ],
   "id": "b57978416d0cdd15"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from PIL import Image\n",
    "from torchvision import transforms"
   ],
   "id": "d887952a467b223b",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "### 格式转换",
   "id": "244d4bc0dabeb8af"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "img = Image.open('files/test.jpg')\n",
    "display(img)\n",
    "print(type(img))\n",
    "\n",
    "# PIL.Image转换为Tensor\n",
    "img1 = transforms.ToTensor()(img)\n",
    "print(type(img1))\n",
    "\n",
    "# Tensor转换为PIL.Image\n",
    "img2 = transforms.ToPILImage()(img1) #PIL.Image.Image\n",
    "print(type(img2))"
   ],
   "id": "5edc708a3fc6089c",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "### Resize",
   "id": "51b08d1164b9cacd"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "from torchvision.transforms import InterpolationMode\n",
    "resize_img_oper = transforms.Resize(\n",
    "    size = (432,648), # resize 大小\n",
    "    interpolation = InterpolationMode.BILINEAR # 插值算法\n",
    ")\n",
    "resize_img = resize_img_oper(img)\n",
    "display(resize_img)"
   ],
   "id": "9cf6d4443233c491",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "### 剪裁",
   "id": "ce675270a337beea"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "center_crop_oper = transforms.CenterCrop((200,200)) # 中心剪裁\n",
    "random_crop_oper = transforms.RandomCrop((100,100)) # 随机剪裁\n",
    "five_crop_oper = transforms.FiveCrop((150,150)) # 中心+四角剪裁\n",
    "\n",
    "center_img = center_crop_oper(img)\n",
    "display(center_img)\n",
    "\n",
    "random_img = random_crop_oper(img)\n",
    "display(random_img)\n",
    "\n",
    "five_imgs = five_crop_oper(img)\n",
    "for single in five_imgs:\n",
    "    display(single)"
   ],
   "id": "a2db23f356eb106a",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "### 翻转",
   "id": "fdc548ff885b0e9a"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "h_flip_oper = transforms.RandomHorizontalFlip(p=0.5) # 随机水平翻转\n",
    "v_flip_oper = transforms.RandomVerticalFlip(p=0.5) # 随机垂直翻转\n",
    "\n",
    "h_img = h_flip_oper(img)\n",
    "display(h_img)\n",
    "v_img = v_flip_oper(img)\n",
    "display(v_img)"
   ],
   "id": "f1cf9608b8ca6bae",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "### 标准化",
   "id": "509ba4c4b9dd8c81"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "norm_oper = transforms.Normalize((0.2, 0.2, 0.2), (0.2, 0.2, 0.2)) # 均值 标准差\n",
    "img_tensor = transforms.ToTensor()(img) # 将图片转为tensor\n",
    "tensor_norm = norm_oper(img_tensor) # 标准化\n",
    "norm_img = transforms.ToPILImage()(tensor_norm)\n",
    "display(norm_img)"
   ],
   "id": "ae98885377aef213",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "### 组合",
   "id": "6fb18a0b96a792c4"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "# 定义组合操作\n",
    "composed = transforms.Compose([transforms.Resize((200, 200)),\n",
    "                               transforms.RandomCrop(100)])\n",
    "com_img = composed(img)\n",
    "display(com_img)"
   ],
   "id": "655f845199b269ac",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "# 读取MNIST数据集 同时做数据变换\n",
    "# mnist_dataset = datasets.MNIST(root='./data',\n",
    "#                                train=False,\n",
    "#                                transform=composed,\n",
    "#                                target_transform=None,\n",
    "#                                download=True)"
   ],
   "id": "1aca869f0c12ebf5",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# Torchvision（下）：其他有趣的功能",
   "id": "bb08d817a37c402b"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": [
    "import torchvision.models as models\n",
    "googlenet = models.googlenet(pretrained=True) # pretrained 是否加载预训练模型\n"
   ],
   "id": "8651f7ee5c41f8f9",
   "outputs": [],
   "execution_count": null
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "torchvision.models模块中所有预训练好的模型，都是在 ImageNet 数据集上训练的，它们都是由 PyTorch 的torch.utils.model_zoo模块所提供的，并且我们可以通过参数  pretrained=True  来构造这些预训练模型。",
   "id": "1716778720cd5ab0"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
